package wykop.dataBase;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.hibernate.Session;

import wykop.page.WykopUser;
import wykop.parser.HibernateUtil;
import wykop.parser.UserProvider;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

/**
 * Class for managing users in the database
 * 
 * @author kad
 * 
 */
public class UserManager {

	private final static Logger logger = Logger.getLogger("wykop.database");
	private final static Map<String, Integer> users = Maps.newConcurrentMap();
	private final static Object lock = new Object();

	/**
	 * Check if a user with the specified name exists in the database. If she
	 * exists, return her. If not, create new user and return her.
	 * 
	 * @param name
	 * @return
	 */
	private static WykopUser getUserForName(final String name) {
		Preconditions.checkNotNull(name);

		logger.debug("Getting user for name: " + name);

		final Session session = HibernateUtil.getSessionFactory()
				.getCurrentSession();

		if (users.containsKey(name)) {
			final Integer id = users.get(name);
			return (WykopUser) session.get(WykopUser.class, id);
		} else {
			synchronized (lock) {
				update();
				if (users.containsKey(name)) {
					final Integer id = users.get(name);
					return (WykopUser) session.get(WykopUser.class, id);
				}
				return newUser(name);
			}
		}

	}

	public static UserProvider getUserProvider() {
		return new UserProvider() {

			@Override
			public WykopUser getUserForName(final String name) {
				return UserManager.getUserForName(name);
			}
		};
	}

	private static WykopUser newUser(final String name) {
		logger.info("Creating user with name: " + name);

		final WykopUser user = new WykopUser();
		user.setName(name);
		final Session session = HibernateUtil.getSessionFactory()
				.getCurrentSession();
		session.save(user);
		users.put(name, user.getId());

		return user;

	}

	private static void update() {
		final Session session = HibernateUtil.getSessionFactory()
				.getCurrentSession();
		final List list = session.createCriteria(WykopUser.class).list();
		for (final Object userAsO : list) {
			final WykopUser user = (WykopUser) userAsO;
			if (!users.containsKey(user.getName())) {
				users.put(user.getName(), user.getId());
			}
		}
	}
}
